import {Injectable} from "@angular/core";
import {LoadingController, ToastController} from "ionic-angular";
import {interfaceUrls} from './serverUrls';
import {Http, Headers} from "@angular/http";

import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/timeout';
import {Device} from "ionic-native";
import moment from "moment";
import 'rxjs/add/operator/map';

declare let hxCampusCard;

@Injectable()
export class services {
    private headers = new Headers({'Content-Type': 'application/json; charset=utf-8'});

    status: number = 0; //0-初始，1-已获取订单，3-加钱成功，4-加钱失败
    items = [];
    phone;
    activeModelText;
    personalDetail = {};


    //校园卡信息
    cardInfo = {
        CardNo: '',        //卡号
        name: '',          //姓名
        balance: null,     //余额
        serialNO: '',      //卡序列号
        listBlock: null,   //扇区列表
        orderId: ''        //订单号
    };
    writeNum: number = -1;    //待写卡金额

    //终端参数
    deviceId: string;
    deviceNo: string;
    merchantNo: string;
    industryCode: string;

    //写卡记录
    list: any[] = [];

    beforeTradeNum: number = -1;
    afterTradeNum: number = -1;

    constructor(public http: Http,
                public toastCtrl: ToastController,
                public loadingCtrl: LoadingController) {
    }

    /**
     * 错误回调
     * @param error
     * @returns {Promise<never>}
     */
    private handleError(error: any): Promise<any> {
        return Promise.reject(error.message || error);
    }

    /**
     * post请求
     * @param url
     * @param param
     * @returns {Promise<TResult|T>}
     */
    postMethod(url: string, param: any): Promise<any> {
        return this.http
            .post(url, JSON.stringify(param), {headers: this.headers})
            .timeout(2000)
            .toPromise()
            .then(response => response.json())
            .catch(this.handleError);
    }

    /**
     * get请求JSON数据
     * @param url
     * @param param
     * @returns {Promise<TResult|T>}
     */
    getData(url: string): Promise<any> {
        return this.http
            .get(url)
            .timeout(2000)
            .toPromise()
            .then(response => response.json())
            .catch(err => {
                return Promise.reject(err)
            })
    }


    /**
     * loading效果
     * @param msg {string} 提示信息
     */
    loading(msg: string): any {
        let loader = this.loadingCtrl.create({
            content: msg,
            spinner: 'ios',
            cssClass: 'myLoading'
        });
        loader.present();
        return loader;
    }

    /**
     * 吐丝方法
     * @param msg
     */
    toast(msg: string): void {
        let toast = this.toastCtrl.create({
            message: msg,
            duration: 3000,
            position: 'bottom',
            cssClass: 'myToast'
        });
        toast.present();
    }

    /**
     * 获取广告
     * @param param
     * @returns {Promise<T>}
     */
    // getAds(param: any): Promise<any> {
    //   return new Promise((resolve, reject) => {
    //     this.postMethod(interfacesUrl.getAds, param)
    //       .then(data => {
    //         resolve(data.context);
    //       })
    //       .catch(err => {
    //         reject(err);
    //       })
    //   });
    // }

    /**
     * 读卡操作
     */
    readCard(): Promise<any> {
        console.log('------------------读卡信息------------------');

        return new Promise((resolve, reject) => {

            //打开实达POS的射频模块
            hxCampusCard.openRFID(() => {
                //检测卡片是否在感应区域
                hxCampusCard.checkCard(() => {
                    //获取校园卡扇区列表
                    hxCampusCard.readCardListBlock(cardListBlock => {
                        console.log('获取校园卡扇区列表成功', cardListBlock);
                        this.cardInfo.serialNO = cardListBlock.cardSno;      //卡序列号
                        this.cardInfo.listBlock = cardListBlock.listBlock;   //扇区列表
                        //获取校园卡信息
                        hxCampusCard.getCardInfo(cardInfo => {
                            console.log('获取校园卡信息成功', cardInfo);
                            this.cardInfo.CardNo = cardInfo.cardId; //卡号
                            this.cardInfo.name = cardInfo.name;     //姓名
                            this.cardInfo.balance = cardInfo.balance; //余额
                            this.beforeTradeNum = cardInfo.balance;

                            resolve(this.cardInfo);
                        }, cardInfoErr => {
                            console.log('获取校园卡信息失败', cardInfoErr);
                            this.toast(`获取卡片信息失败`);
                            reject(cardInfoErr);
                        });
                    }, cardListBlockErr => {
                        console.log('获取校园卡扇区列表失败', cardListBlockErr);
                        this.toast('获取校园卡扇区列表失败，请重试');
                        reject(cardListBlockErr);
                    });
                }, checkCardErr => {
                    console.log('检测卡片是否在感应区域参数', checkCardErr);

                    this.toast('未检测到卡片，请贴紧卡片重试');
                    reject(checkCardErr);
                }, {
                    timeout: 10 //超时时间，单位：秒
                });
            }, openRFIDErr => {
                console.log('打开射频模块失败，参数', openRFIDErr);
                reject(openRFIDErr);
            });
        });
    }

    /**
     * 取消检测卡片
     * @returns {Promise<T>}
     */
    cancelReadCard(): Promise<any> {
        return new Promise((resolve, reject) => {
            hxCampusCard.cancelCheckCard(data => {
                console.log('取消检测成功返回');
                resolve(data);
            }, err => {
                console.log('取消检测失败返回');
                reject(err);
            })
        });
    }

    /**
     * 查询订单(总共三次)
     * @param card
     * @returns {Promise<T>}
     */
    getTradeOrder(card: any): Promise<any> {
        console.log('------------------查询订单------------------');

        let index = 1;
        return new Promise((resolve, reject) => {
            this.getTradeOrderRec(card, index)
                .then(data => {
                    console.log('查询订单成功', data);

                    resolve(data);
                })
                .catch(err => {
                    console.log('查询订单失败', err);

                    this.toast(`查询订单失败，${err}`);
                    reject(err);
                });
        });
    };

    /**
     * 递归查询订单（共三次）
     * @param card
     * @param index
     * @returns {Promise<TResult|TResult>}
     */
    getTradeOrderRec(card: any, index: number): Promise<any> {
        console.log(`第${index}次查询`);

        return new Promise((resolve, reject) => {
            this.postMethod(interfaceUrls.initDelive, card)
                .then(data => {

                    //查询订单成功
                    if (data.retCode == '0000') {
                        console.log(`第${index}次查询成功`, data);

                        this.cardInfo.orderId = data.context.orderId;
                        if (Number(data.context.totalResult) != 0) {
                            console.log(`有待写卡金额，${data.context.totalResult}`);
                            this.writeNum = Number(data.context.totalResult);   //待写卡金额(分)
                        } else {
                            console.log('无待写卡金额', data.context.totalResult);

                            this.writeNum = 0;    //待写卡金额（分）
                            this.afterTradeNum = this.beforeTradeNum;
                        }
                        resolve(data.context);
                    } else {
                        console.log(`第${index}次查询失败3`, data);

                        if (index <= 2) {
                            return this.getTradeOrderRec(card, index + 1);
                        }
                        reject(data);
                    }
                })
                //通信问题
                .catch(err => {
                    console.log(`第${index}次查询失败`, err);
                    reject(err);
                });
        })
    }

    /**
     * 写卡操作
     */
    writeCard(order: any): Promise<any> {
        console.log('------------------写卡操作------------------');

        return new Promise((resolve, reject) => {
            //设置D密钥
            hxCampusCard.setCardDKey(data1 => {
                console.log('设置D密钥返回', data1);

                //获取校园卡信息，包括卡号，姓名，余额
                hxCampusCard.getCardInfo(data2 => {
                    console.log('获取校园卡信息返回', data2);

                    this.cardInfo = {
                        CardNo: data2.cardId, //卡号
                        name: data2.name, //姓名
                        balance: data2.balance, //余额
                        serialNO: this.cardInfo.serialNO, //卡序列号
                        listBlock: this.cardInfo.listBlock, //扇区列表
                        orderId: this.cardInfo.orderId
                    };
                    //判断余额是否相同
                    if (this.cardInfo.balance != data2.balance) {
                        this.toast('卡异常，中止处理，请联系客服');
                        this.cardInfo.balance = data2.balance;
                        reject(this.cardInfo);
                    }

                    //向校园卡加钱
                    hxCampusCard.addMoney(data3 => {
                        console.log('向校园卡加钱返回', data3);

                        //获取校园卡信息，包括卡号，姓名，余额(验证卡片余额)
                        hxCampusCard.getCardInfo(data4 => {
                            console.log('获取校园卡信息返回', data4);
                            //判断充值后，余额是否正确
                            if (data4.balance == Number(order.totalResult) + data2.balance) {
                                console.log('写卡成功。');
                                this.toast('写卡成功');

                                this.writeNum = Number(order.totalResult);
                                this.cardInfo.balance = data4.balance;
                                //写卡后余额
                                this.afterTradeNum = data4.balance;

                                this.cardInfo = {
                                    CardNo: data4.cardId, //卡号
                                    name: data4.name, //姓名
                                    balance: data4.balance, //余额
                                    serialNO: this.cardInfo.serialNO, //卡序列号
                                    listBlock: this.cardInfo.listBlock, //扇区列表
                                    orderId: this.cardInfo.orderId
                                };

                                resolve(this.cardInfo);
                            } else {
                                console.log(`写卡失败。`);
                                this.toast('写卡异常，请联系客服');
                                console.log(`余额对比,充值前${data2.balance},充值后${data4.balance}`);

                                this.cardInfo = {
                                    CardNo: data4.cardId, //卡号
                                    name: data4.name, //姓名
                                    balance: this.cardInfo.balance, //余额
                                    serialNO: this.cardInfo.serialNO, //卡序列号
                                    listBlock: this.cardInfo.listBlock, //扇区列表
                                    orderId: this.cardInfo.orderId
                                };

                                this.cardInfo.balance = data4.balance;
                                reject(this.cardInfo);
                            }
                        }, err4 => {
                            console.log(err4, '获取校园卡信息参数', null);
                            this.toast('写卡成功');

                            this.writeNum = Number(order.totalResult);
                            this.cardInfo = {
                                CardNo: this.cardInfo.CardNo, //卡号
                                name: this.cardInfo.name, //姓名
                                balance: this.cardInfo.balance + Number(order.totalResult), //余额
                                serialNO: this.cardInfo.serialNO, //卡序列号
                                listBlock: this.cardInfo.listBlock, //扇区列表
                                orderId: this.cardInfo.orderId
                            };

                            //写卡成功状态
                            this.status = 3;
                            resolve(this.cardInfo);
                        });
                    }, err3 => {
                        console.log('向校园卡加钱失败', err3);
                        this.toast('写卡失败，请重新放入正确的卡片');

                        //写卡失败状态
                        this.status = 4;
                        reject(this.cardInfo);
                    }, {
                        money: Number(order.totalResult) //写卡金额，单位：分
                    })
                }, err2 => {
                    console.log(err2, '获取校园卡信息参数', null);
                    this.toast('获取校园卡信息失败，请联系客服');

                    //写卡失败状态
                    this.status = 4;
                    reject(this.cardInfo);
                })
            }, err1 => {
                console.log(err1, '设置D密钥参数', {DKey: order.DKey});
                this.toast('设置DKey失败，请联系客服');

                //写卡失败状态
                this.status = 4;
                reject(this.cardInfo);
            }, {
                DKey: order.DKey //D密钥
            })
        })
    }

    /**
     * 发送后台交易记录
     * @param writeCardReturn
     * @param status
     */
    sendBackEnd(writeCardReturn: any, status: number) {
        let params;
        //写卡成功
        if (typeof writeCardReturn == "string") {
            params = {
                time: moment().format('YYYY-MM-DD HH:mm:ss'),
                termID: '111111',
                MAC: Device.uuid,
                cardID: this.cardInfo.CardNo,
                name: this.cardInfo.name,
                serialNO: this.cardInfo.serialNO,
                orderNO: this.cardInfo.orderId,
                state: status,
                preBalance: this.beforeTradeNum,
                aftBalance: this.afterTradeNum,
                amount: writeCardReturn
            }
        } else {
            params = {
                time: moment().format('YYYY-MM-DD HH:mm:ss'),
                termID: '111111',
                MAC: Device.uuid,
                cardID: writeCardReturn.CardNo,
                name: writeCardReturn.name,
                serialNO: writeCardReturn.serialNO,
                orderNO: writeCardReturn.orderId,
                state: status,
                preBalance: this.beforeTradeNum,
                aftBalance: writeCardReturn.balance,
                amount: writeCardReturn.balance - this.beforeTradeNum
            }
        }
        console.log('发送后台交易记录参数', params);
        this.postMethod(interfaceUrls.commitDelive, params)
            .then(data => {
                console.log('发送后台交易记录返回', data);
                if (data.retCode == '0000') {
                    console.log('发送后台交易记录成功');
                } else {
                    console.log('发送后台交易记录失败，请联系客服', data);
                }

                //重置状态
                this.status = 0;
            })
            .catch(err => {
                console.log('发送后台交易记录失败，请联系客服。', err);

                //重置状态
                this.status = 0;
            });
    }

    /**
     * 获取写卡记录
     * @param param
     * @returns {Promise<T>}
     */
    getRecords(param: any): Promise<any> {
        return new Promise((resolve, reject) => {
            console.log(interfaceUrls.getRecord);
            this.postMethod(interfaceUrls.getRecord, param)
                .then(data => {
                    console.log('获取写卡记录返回', data);
                    if (data.retCode == '0000') {
                        console.log('获取写卡记录成功');

                        if (param.pageIndex == 0) {
                            if (data.context.writeList.length == 0) {
                                this.toast('没有查到数据，/(ㄒoㄒ)/~~');
                            }
                            this.list = data.context.writeList;
                        } else {
                            this.list = this.list.concat(data.context.writeList);
                        }
                        resolve(data.context.writeList);
                    } else {
                        console.log('获取写卡记录失败');
                        this.toast(`获取写卡记录失败，${data.retMsg || data}`);
                        this.list = [];
                        reject(data.retMsg);
                    }
                })
                .catch(err => {
                    this.toast(`获取写卡记录失败，${err.retMsg || err}`);
                    console.log('获取写卡记录失败');
                    this.list = [];
                    reject();
                })
        })
    }

    /**
     * 获取设备参数
     * @param param
     * @returns {Promise<T>}
     */
    getDeviceParams(param: any): Promise<any> {
        let loader = this.loading('下载参数中...');
        return new Promise((resolve, reject) => {
            this.postMethod(interfaceUrls.getParams, param)
                .then(data => {
                    console.log('获取设备参数返回', data);
                    if (data.retCode == '0000') {
                        console.log('获取设备参数成功');
                        this.deviceId = data.context.id;
                        this.deviceNo = data.context.deviceNo;
                        this.merchantNo = data.context.merchantNum;
                        this.industryCode = data.context.industryCode;

                        localStorage.setItem('deviceId', this.deviceId);
                        localStorage.setItem('deviceNo', this.deviceNo);

                        loader.dismiss();
                        this.toast(`下载参数成功，行业编号:${this.industryCode},商户号:${this.merchantNo}`);
                        resolve();
                    } else {
                        console.log('获取设备参数失败');
                        loader.dismiss();
                        this.toast(`获取设备参数失败，${data.retMsg || data}`);
                        reject();
                    }
                })
                .catch(err => {
                    loader.dismiss();
                    this.toast(`获取设备参数失败，${err.retMsg || err}`);
                    console.log('获取设备参数失败');
                    reject();
                })
        })
    }

    /**
     * 修改终端编号
     * @param param
     * @returns {Promise<T>}
     */
    changeDeviceParams(param: any): Promise<any> {
        let loader = this.loading('下载参数中...');
        return new Promise((resolve, reject) => {
            this.postMethod(interfaceUrls.changeParams, param)
                .then(data => {
                    console.log('修改设备参数返回', data);
                    if (data.retCode == '0000') {
                        console.log('修改设备参数成功');
                        this.deviceNo = data.context.deviceNo;
                        this.merchantNo = data.context.merchantNum;
                        this.industryCode = data.context.industryCode;


                        localStorage.removeItem('deviceNo');
                        localStorage.setItem('deviceNo', this.deviceNo);

                        loader.dismiss();
                        this.toast(`行业编号:${this.industryCode},商户号:${this.merchantNo}`);
                        resolve();
                    } else {
                        console.log('修改设备参数失败');

                        loader.dismiss();
                        this.toast(`修改设备参数失败，${data.retMsg || data}`);
                        reject();
                    }
                })
                .catch(err => {
                    loader.dismiss();
                    this.toast(`获取设备参数失败，${err.retMsg || err}`);
                    console.log('获取设备参数失败');
                    reject();
                })
        })
    }

    /**
     * 告诉爸妈充钱
     * @param param
     * @returns {Promise<T>}
     */
    tellParents(param: any): Promise<any> {
        return new Promise((resolve, reject) => {
            this.postMethod(interfaceUrls.tellParents, param)
                .then(data => {
                    if (data.retCode == '0000') {
                        this.toast(`已经通知爸妈啦！`);
                        resolve();
                    }
                    reject(data.retMsg);
                })
                .catch(err => {
                    this.toast(`没通知成功，再试一次吧`);
                    reject();
                })
        })
    }
}
